package com.tjakus.quartz;

import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import org.apache.http.entity.mime.MultipartEntity;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.tjakus.adv.Advertisement;
import com.tjakus.adv.UserData;
import com.tjakus.http.HttpTokenAndNonce;
import com.tjakus.http.HttpTrafficManager;
import com.tjakus.logging.Logging;
import com.tjakus.parser.HttpContentParser;
import com.tjakus.userdata.UserDataList;

/**
 * This class represents Quartz job which is responsible for renewing
 * advertisement for all users.
 * 
 * @author tjakus
 * 
 */

public class RenewAdvertisementJob implements Job {

	/**
	 * This method is called when schedule trigger occurs. It is responsible to
	 * reactivate all advertisements for all users.
	 * 
	 */
	public void execute(JobExecutionContext context) throws JobExecutionException {

		Logging.getLogger().info("RenewAdvertisementJob - execute [ STARTED ] ");
		// Initialize HttpTraffinManager
		HttpTrafficManager.initializeHttpTrafficManager();
		// Get minutes from current date
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int minutes = calendar.get(Calendar.MINUTE);
		Logging.getLogger().debug(
				"RenewAdvertisementJob - execute - time: [ " + minutes + " ] ");
		// Get groupId from minutes
		int group = minutes % 30;
		Logging.getLogger().debug(
				"RenewAdvertisementJob - execute - groupId: [ " + group + " ] ");
		// Reactivate adds for all users
		for (Iterator<UserData> iter = UserDataList.getUserDataList().iterator(); iter
				.hasNext();) {
			UserData userData = iter.next();
			// if (userData.getGroupId() == group) {
			this.renewAdvertisementsForUser(userData);
			// Initialize HTTP Traffic Manager for every user to reset connection
			HttpTrafficManager.initializeHttpTrafficManager();
			// }
		}
		// Close connection
		HttpTrafficManager.closeAllConnections();
		Logging.getLogger().info("RenewAdvertisementJob - execute [ FINISHED ] ");
	}

	/**
	 * This method will renew all advertisements for user. It will send all HTTP
	 * requests required for this.
	 * 
	 */
	private void renewAdvertisementsForUser(UserData userData) {

		boolean status;
		String cookies;
		String httpGetUrl;

		Logging.getLogger().info(
				"RenewAdvertisementJob - renewAdvertisementsForUser [ "
						+ userData.getUserName() + " ] ");

		// HTTP GET to get cookie
		httpGetUrl = "https://www.njuskalo.hr/prijava/?return_url=http://www.njuskalo.hr%2F";
		cookies = HttpTrafficManager.sendHttpGetToGetCookies(httpGetUrl);
		// If cookies are unable to retrieve, exit from method
		if (cookies == null) {
			Logging.getLogger().error(
					"RenewAdvertisementJob - "
							+ "renewAdvertisementsForUser [ cookies are null ]");
			return;
		}
		// HTTP POST request for log in with cookies
		status = this.createAndSendPostWithUserAndPassword(userData, cookies);
		// If unable to log in, exit from method
		if (!status) {
			Logging.getLogger().error(
					"RenewAdvertisementJob - "
							+ "renewAdvertisementsForUser [ unable to log in ]");
			return;
		}
		// HTTP GET to get my active adds and userId:
		userData = this.createAndSendGetToRetrieveUserIdAndActiveAdds(userData,
				cookies);
		// If unable to get active adds and userId, log out and exit from method
		if (userData == null) {
			Logging
					.getLogger()
					.error(
							"RenewAdvertisementJob - "
									+ "renewAdvertisementsForUser [ unable to get active adds and user id ]");
			this.sendHttpGetToLogOut(cookies);
			return;
		}
		// If deactivation of advertisement is necessary
		for (Iterator<String> iter = userData.getAdvertisementIdsToDelete()
				.iterator(); iter.hasNext();) {
			String advertisementId = iter.next();
			// HTTP GET to delete adds with cookies:
			status = this.deleteActiveAdvertisement(userData.getUserId(),
					advertisementId, cookies);
			// If unable to deactivate, log out and exit from method
			if (!status) {
				Logging
						.getLogger()
						.error(
								"RenewAdvertisementJob - "
										+ "renewAdvertisementsForUser [ unable to deactivate advertisement ]");
				this.sendHttpGetToLogOut(cookies);
				return;
			}
		}

		// Activation of advertisements
		for (Iterator<Advertisement> iter = userData.getAdvertisements().iterator(); iter
				.hasNext();) {
			Advertisement adv = iter.next();
			// HTTP POST request to set category id
			this.httpPostToCreateNewAdvertisement(adv.getAdvertisementCategoryId(),
					cookies);
			// HTTP GET request to get token
			HttpTokenAndNonce httpTokenAndNonce = this
					.httpGetToRetrieveTokenAndNonce(cookies);
			// HTTP post request to append pictures
			for (Iterator<String> iter2 = adv.getPictures().iterator(); iter2
					.hasNext();) {
				this.httpPostToAppendPicture(iter2.next(), cookies,
						httpTokenAndNonce.getToken());
			}
			// HTTP post request for renewing add with cookies
			this.httpPostToRenewAdvertisementById(adv, cookies, httpTokenAndNonce);
		}
		// HTTP get to log out
		this.sendHttpGetToLogOut(cookies);
	}

	/**
	 * This method creates and sends HTTP POST with user name and password.
	 * 
	 */
	private boolean createAndSendPostWithUserAndPassword(UserData userData,
			String cookies) {
		// HTTP POST request for log in with cookies
		String httpPostUrl = "https://www.njuskalo.hr/prijava/?return_url=http%3A%2F%2Fwww.njuskalo.hr%2F";
		// Create POST body with user name and password
		String postContent = "ed_username=" + userData.getUserName()
				+ "&ed_password=" + userData.getPassword() + "&fb_login_active=0";
		boolean status = HttpTrafficManager.sendHttpPostWithStringContent(
				httpPostUrl, cookies, postContent);
		return status;
	}

	/**
	 * This method creates and sends HTTP GET to retrieve user id and active
	 * advertisement ids. It also checks if it is necessary to deactivate
	 * advertisement.
	 * 
	 */
	private UserData createAndSendGetToRetrieveUserIdAndActiveAdds(
			UserData userData, String cookies) {
		// HTTP get to get my active adds and userId:
		String httpGetUrl = "https://www.njuskalo.hr/moje-njuskalo/";
		String bodyData = HttpTrafficManager.sendHttpGet(httpGetUrl, cookies);
		// If body data is retrieved from HTTP GET response
		if (bodyData != null) {
			// Find user id from body data
			userData.setUserId(HttpContentParser.getUserIdFromContent(bodyData));
			// Find advertisement ids from body data
			userData.setAdvertisementIdsToDelete(HttpContentParser
					.getListOfAdvertisementIdFromContent(bodyData));
			return userData;
		}
		// Body data was not retrieved, no need for deactivation and reactivation
		else {
			return null;
		}
	}

	/**
	 * This method creates and sends HTTP GET to deactivate advertisement.
	 * 
	 */
	private boolean deleteActiveAdvertisement(String userId,
			String advertisementId, String cookies) {
		// HTTP get to delete add with cookies:
		String httpGetUrl = "https://www.njuskalo.hr/moje-njuskalo/index.php?ctl=user_account&action=mass_delete&ad_id="
				+ advertisementId + "&f_user_id=" + userId + "&publisher_id=0";
		String response = HttpTrafficManager.sendHttpGet(httpGetUrl, cookies);
		if (response == null) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * This method creates and sends HTTP GET to retrieve token and nonce
	 * 
	 */
	private HttpTokenAndNonce httpGetToRetrieveTokenAndNonce(String cookies) {
		// HTTP GET request to get category id and advertisement details for
		// advertisement:
		String httpGetUrl = "https://www.njuskalo.hr/index.php?ctl=ad_editor&action=edit_ad";
		String bodyData = HttpTrafficManager.sendHttpGet(httpGetUrl, cookies);
		if (bodyData != null) {
			HttpTokenAndNonce tokenAndNonce = new HttpTokenAndNonce();
			tokenAndNonce.setToken(HttpContentParser.getTokenFromContent(bodyData));
			tokenAndNonce.setNonce(HttpContentParser.getNonceFromContent(bodyData));
			return tokenAndNonce;
		} else {
			return null;
		}
	}

	/**
	 * This method creates and sends HTTP POST with string content to create new
	 * advertisement
	 * 
	 */
	private boolean httpPostToCreateNewAdvertisement(String categoryId,
			String cookies) {
		// HTTP post request for renewing add with cookies
		String httpPostUrl = "https://www.njuskalo.hr/index.php?ctl=ad_editor&action=select_pricing_model";
		// Add String data for categoryId description
		String postContent = "category_id=" + categoryId
				+ "&product_id=0&variation_id=0";
		return HttpTrafficManager.sendHttpPostWithStringContent(httpPostUrl,
				cookies, postContent);
	}

	/**
	 * This method creates and sends HTTP POST with picture as MIME content
	 * 
	 */
	private boolean httpPostToAppendPicture(String picture, String cookies,
			String token) {
		// HTTP post request for renewing add with cookies
		String httpPostUrl = "https://www.njuskalo.hr/index.php?ctl=image_iframe_uploader&action=handle_upload&input_token="
				+ token + "&temp_image_type_id=10&max_image_count=10";
		// Add MIME data for advertisement picture
		MultipartEntity mimeEntity = HttpContentParser
				.createMimeContentWithPicture(picture);
		return HttpTrafficManager.sendHttpPostWithMimeContent(httpPostUrl, cookies,
				mimeEntity);
	}

	/**
	 * This method creates and sends HTTP POST with MIME content
	 * 
	 */
	private boolean httpPostToRenewAdvertisementById(Advertisement advertisement,
			String cookies, HttpTokenAndNonce newHttpTokenAndNonce) {
		// HTTP post request for renewing add with cookies
		String httpPostUrl = "https://www.njuskalo.hr/index.php?ctl=ad_editor&action=save_ad&input_token="
				+ newHttpTokenAndNonce.getToken()
				+ "&nonce="
				+ newHttpTokenAndNonce.getNonce();
		// Add MIME data for advertisement description
		MultipartEntity mimeEntity = HttpContentParser
				.createMimeContent(advertisement);
		return HttpTrafficManager.sendHttpPostWithMimeContent(httpPostUrl, cookies,
				mimeEntity);
	}

	/**
	 * This method creates and sends HTTP GET to log out
	 * 
	 */
	private boolean sendHttpGetToLogOut(String cookies) {
		// HTTP get to log out
		String httpGetUrl = "https://www.njuskalo.hr/odjava/?return_url=http://www.njuskalo.hr%2F";
		String status = HttpTrafficManager.sendHttpGet(httpGetUrl, cookies);
		if (status == null) {
			return false;
		} else {
			return true;
		}
	}

}
